﻿using Helpers.Enums;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
using Helpers.Factories;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Serilog;
using System.Text.RegularExpressions;

namespace Helpers.Attributes
{
    /// <summary>
    /// 使用weedfs进行缓存
    /// 支持返回结果类型是OkObjectResult,JsonResult
    /// </summary>
    public class SimpleWeedFsCacheAttribute : Attribute, IAsyncActionFilter
    {
        /// <summary>
        /// 缓存时间的key
        /// </summary>
        private const string TTLKEY = "x-ttl";

        /// <summary>
        /// 缓存时间,默认是24h,传0会刷新缓存
        /// </summary>
        public string CacheTtl { get; set; } = ApiCacheOptions.DefaultTtl;
        /// <summary>
        /// 缓存路径,默认是从httpRequest.Path获取
        /// </summary>
        public string CachePath { get; set; }
        /// <summary>
        /// 非空时对结果进行匹配 匹配成功才缓存
        /// </summary>
        public string IncludeCacheRegex { get; set; }
        /// <summary>
        /// 非空时对结果进行匹配 匹配成功不缓存
        /// </summary>
        public string ExcludeCacheRegex { get; set; }

        private readonly CacheKeyBuildFromEnum _cacheKeyBuildFrom;
        private readonly string[] _keyNames;

        /// <summary>
        /// 从querystring读取cachekey
        /// </summary>
        /// <param name="keyNames"></param>
        public SimpleWeedFsCacheAttribute(params string[] keyNames) : this(CacheKeyBuildFromEnum.Query, keyNames)
        {
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="cacheKeyBuildFrom"></param>
        /// <param name="keyNames">默认使用queryString的md5作为key</param>
        public SimpleWeedFsCacheAttribute(CacheKeyBuildFromEnum cacheKeyBuildFrom, params string[] keyNames)
        {
            _cacheKeyBuildFrom = cacheKeyBuildFrom;
            _keyNames = keyNames;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            try
            {
                //获取cacheKey
                string cacheKey;
                if (string.IsNullOrWhiteSpace(CachePath))
                {
                    cacheKey = CacheKeyFactory.GetCacheKey(context.HttpContext.Request, _cacheKeyBuildFrom, _keyNames);
                }
                else
                {
                    cacheKey = CacheKeyFactory.GetCacheKey(CachePath, context.HttpContext.Request, _cacheKeyBuildFrom, _keyNames);
                }

                //是否刷新缓存
                var ttl = CacheKeyFactory.Build(context.HttpContext.Request, CacheKeyBuildFromEnum.All, TTLKEY);
                //通过refresh刷新缓存
                var refresh = CacheKeyFactory.Build(context.HttpContext.Request, CacheKeyBuildFromEnum.Query, "refresh");
                if (string.IsNullOrEmpty(refresh))
                {
                    refresh = CacheKeyFactory.Build(context.HttpContext.Request, CacheKeyBuildFromEnum.Query, "isrefresh");
                }
                if (ttl != "0" && refresh != "1" && !string.Equals(refresh, "true", StringComparison.OrdinalIgnoreCase))
                {
                    //读缓存
                    var cacheData = await WeedFsHttpClient.Instance.GetAsync(cacheKey);
                    if (!string.IsNullOrWhiteSpace(cacheData))
                    {
                        var contentResult = new ContentResult
                        {
                            StatusCode = 201,
                            Content = cacheData
                        };
                        context.Result = contentResult;
                        return;
                    }
                }
                //else
                //{
                //    //删缓存
                //    //await WeedFsHttpClient.Instance.DelAsync(cacheKey);
                //}

                var nextRet = await next();

                //保存缓存
                object cacheValue = null;
                if (nextRet.Result is ObjectResult objResult)
                {
                    cacheValue = objResult.Value;
                }
                else if (nextRet.Result is JsonResult jsonResult)
                {
                    cacheValue = jsonResult.Value;
                }
                if (cacheValue != null)
                {
                    var cacheValueStr = cacheValue is string ? cacheValue.ToString() : JsonConvert.SerializeObject(cacheValue);
                    if (!string.IsNullOrWhiteSpace(IncludeCacheRegex) && !Regex.IsMatch(cacheValueStr, IncludeCacheRegex))
                    {
                        return;
                    }
                    if (!string.IsNullOrWhiteSpace(ExcludeCacheRegex) && Regex.IsMatch(cacheValueStr, ExcludeCacheRegex))
                    {
                        return;
                    }
                    var cacheTll = string.IsNullOrWhiteSpace(ttl) ? CacheTtl : ttl;
                    await WeedFsHttpClient.Instance.AddAsync(cacheKey, cacheValueStr, cacheTll);
                }
            }
            catch (Exception ex)
            {
                Log.Error($"weedfs缓存异常-{context.HttpContext.Request.Path}{context.HttpContext.Request.QueryString}--{ex.Message}");
            }
        }
    }
}
